#include <sys/types.h>
#include <sys/socket.h>
#include <boost/bind.hpp>
#include <errno.h>
#include <event2/event.h>
#include <iostream>
#include <string.h>

#include "workers.h"

struct Handle {
    event_base *base;
    event      *ev;
    Workers    *workers;    
};

void proxy_accept(evutil_socket_t fd, short flag, void *arg);

int main()
{
    // 先起多线程
    Workers *workers = new Workers(10);
    workers->start();

    struct sockaddr_in server_addr;
    int m_server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (m_server_fd == -1) {
        printf("socket fail\n");
        ::exit(1);
    }
    
    evutil_make_socket_nonblocking(m_server_fd);
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family      = AF_INET;
    server_addr.sin_port        = htons(5060);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    
    if (bind(m_server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        printf("bind fail\n");
        ::exit(1);
    }

    printf("%d\n", listen(m_server_fd, 20));
    Handle *h = new Handle();
    event_base *base = event_base_new();
    event *ev = event_new(base, m_server_fd, EV_READ|EV_WRITE|EV_PERSIST, proxy_accept, (void*)h);

    h->base = base;
    h->ev = ev;
    h->workers = workers;
    if (0 != event_add(h->ev, NULL)) {
        std::cout << "event_add fail" << std::endl;
        return 0;
    }
    
    int loop_ret = event_base_dispatch(base); // not return
    std::cout << "server over " << loop_ret << std::endl;

    return 0;
}

void proxy_accept(evutil_socket_t fd, short flag, void *arg) {
    Handle *h = (Handle*)arg;

    sockaddr client;
    socklen_t len;
    int accept_fd = accept(fd, &client, &len); 
    
    printf("accept_fd %d\n", accept_fd);

    if (accept_fd > 0) {
        //printf("accept succ\n");
        h->workers->send_task_to_worker(accept_fd);
    } else {
        printf("accept fail [%d]\n", errno);
    }
}
